﻿namespace Pngcs.Zlib
{
	public class Adler32
	{
		uint a = 1;
		uint b = 0;
		const int _base = 65521; /* largest prime smaller than 65536 */
		const int _nmax = 5550;
		int pend = 0; // how many bytes have I read witouth computing modulus

		public void Update ( byte data )
		{
			if( pend>=_nmax) updateModulus();
			a += data;
			b += a;
			pend++;
		}

		public void Update ( byte[] data ) => Update( data , 0 , data.Length );

		public void Update ( byte[] data , int offset , int length )
		{
			int nextJToComputeModulus = _nmax - pend;
			for( int j=0 ; j<length ; j++ )
			{
				if( j==nextJToComputeModulus )
				{
					updateModulus();
					nextJToComputeModulus = j + _nmax;
				}
				unchecked
				{
					a += data[j+offset];
				}
				b += a;
				pend++;
			}
		}

		public void Reset ()
		{
			a = 1;
			b = 0;
			pend = 0;
		}

		void updateModulus ()
		{
			a %= _base;
			b %= _base;
			pend = 0;
		}

		public uint GetValue ()
		{
			if( pend>0 ) updateModulus();
			return b<<16 | a;
		}
		
	}
}
